package com.ecoolex.ying.space.core.manager;

import com.ecoolex.framework.common.enums.ResultCode;
import com.ecoolex.framework.common.pojo.Page;
import com.ecoolex.framework.common.pojo.Pagination;
import com.ecoolex.framework.common.pojo.Sorting;
import com.ecoolex.framework.common.pojo.Sortings;
import com.ecoolex.framework.common.util.BizAssert;
import com.ecoolex.framework.common.util.Check;
import com.ecoolex.ying.space.core.dao.GoodsCategoryDAO;
import com.ecoolex.ying.space.entity.GoodsCategory;
import com.ecoolex.ying.space.entity.GoodsCategory.Column;
import com.ecoolex.ying.space.entity.GoodsCategoryExample;
import com.ecoolex.ying.space.pojo.QueryGoodsCategoryDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Instant;
import java.util.Date;
import java.util.List;

@Service
public class GoodsCategoryManager {
    @Autowired
    private GoodsCategoryDAO dao;

    private GoodsCategory verify(GoodsCategory record) {
        BizAssert.isTrue(Check.notNullOrTrimEmpty(record.getName()), ResultCode.VERIFY.build(10), "名称不能为空");
        if (Check.isNullOrLtOne(record.getParentCategoryId())) {
            return null;
        } else {
            GoodsCategory parent = getById(record.getParentCategoryId());
            BizAssert.isTrue(Check.notNull(parent), ResultCode.BIZ.build(1), "父级分类不存在");
            return parent;
        }
    }

    public GoodsCategory add(GoodsCategory record, String createUser) {
        GoodsCategory parent = verify(record);
        if (Check.isNull(parent)) {
            record.setParentCategoryId(0);
            record.setLevel(1);
        } else {
            record.setParentCategoryId(parent.getCategoryId());
            record.setLevel(parent.getLevel() + 1);
        }

        record.setIsShow(true);
        record.setDeleted(GoodsCategory.NOT_DELETED);
        record.setCreateUser(createUser);
        record.setCreateTime(Date.from(Instant.now()));
        record.setUpdateUser(createUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.insert(record);
        return record;
    }

    public GoodsCategory update(GoodsCategory record, String updateUser) {
        GoodsCategory parent = verify(record);
        if (Check.isNull(parent)) {
            record.setParentCategoryId(0);
            record.setLevel(1);
        } else {
            record.setParentCategoryId(parent.getCategoryId());
            record.setLevel(parent.getLevel() + 1);
        }

        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(record,
                Column.excludes(Column.isShow, Column.deleted, Column.createUser, Column.createTime));
        return record;
    }

    public void delete(GoodsCategory record, String updateUser) {
        GoodsCategoryExample example = new GoodsCategoryExample();
        example.createCriteria().andParentCategoryIdEqualTo(record.getCategoryId()).andDeletedEqualTo(
                GoodsCategory.NOT_DELETED);
        long childCount = dao.countByExample(example);
        BizAssert.isTrue(childCount < 1, ResultCode.BIZ.build(1), "存在{}个子分类,无法删除", childCount);

        record.setDeleted(GoodsCategory.IS_DELETED);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(record, Column.deleted, Column.updateUser, Column.updateTime);
    }

    public GoodsCategory getById(Integer categoryId) {
        return dao.selectByPrimaryKeyWithLogicalDelete(categoryId, GoodsCategory.NOT_DELETED);
    }

    public List<GoodsCategory> queryByParentId(Integer parentCategoryId, Boolean isShow) {
        GoodsCategoryExample example = new GoodsCategoryExample();
        GoodsCategoryExample.Criteria criteria = example.createCriteria();
        criteria.andParentCategoryIdEqualTo(parentCategoryId);

        if (Check.notNull(isShow)) {
            criteria.andIsShowEqualTo(isShow);
        }

        criteria.andDeletedEqualTo(GoodsCategory.NOT_DELETED);
        example.orderBy(Column.sorting.asc());

        return dao.selectByExample(example);
    }

    public Pagination<GoodsCategory> query(QueryGoodsCategoryDTO query, Sorting[] sorts, Page page) {
        GoodsCategoryExample example = new GoodsCategoryExample();
        GoodsCategoryExample.Criteria criteria = example.createCriteria();

        if (Check.notNull(query.getParentCategoryId())) {
            criteria.andParentCategoryIdEqualTo(query.getParentCategoryId());
        }
        if (Check.notNull(query.getLevel())) {
            criteria.andLevelEqualTo(query.getLevel());
        }
        if (Check.notNullOrTrimEmpty(query.getName())) {
            criteria.andNameLike('%' + query.getName()
                    + '%');
        }
        if (Check.notNull(query.getIsShow())) {
            criteria.andIsShowEqualTo(query.getIsShow());
        }

        criteria.andDeletedEqualTo(GoodsCategory.NOT_DELETED);

        example.orderBy(Sortings.builder(sorts).verify(Column::valueOf).toSql());
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());

        return Pagination.create(page, dao.countByExample(example), () -> dao.selectByExample(example));
    }
    
    public Pagination<GoodsCategory> queryCategoryForH5(Integer parentCategoryId, Page page){
    	GoodsCategoryExample example = new GoodsCategoryExample();
        GoodsCategoryExample.Criteria criteria = example.createCriteria();
        criteria.andParentCategoryIdEqualTo(parentCategoryId).andIsShowEqualTo(true).andDeletedEqualTo(GoodsCategory.NOT_DELETED);
        example.setOffset(page.getFirstIndex());
        example.setRows(page.getPageSize());
        example.orderBy(Column.sorting.desc());
        return Pagination.create(page, dao.countByExample(example),() -> dao.selectByExample(example));
    }

    public GoodsCategory show(GoodsCategory record, String updateUser) {
        record.setIsShow(true);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(java.sql.Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(record, Column.isShow, Column.updateUser, Column.updateTime);
        return record;
    }

    public GoodsCategory hide(GoodsCategory record, String updateUser) {
        record.setIsShow(false);
        record.setUpdateUser(updateUser);
        record.setUpdateTime(java.sql.Date.from(Instant.now()));
        dao.updateByPrimaryKeySelective(record, Column.isShow, Column.updateUser, Column.updateTime);
        return record;
    }

}